<?php

class MRouter extends MSingleton {
    const ROUTE_PATH = 'path';
    const ROUTE_GET = 'get';
    const DEFAULT_ROUTE_VAR = 'r';
    const MODULE_ADMIN_ROUTE_VAR = 'module';

    public $defaultController = 'home';
    public $defaultAction = 'index';
    public $routeVar = self::DEFAULT_ROUTE_VAR;
    public $routeStyle = self::ROUTE_GET; //PATH don't work

    public function route(MRequest $request) {
        $requestArray = parse_url($request->getUrl());
        $path = $requestArray['path'];
        $args = array();
        if (isset($requestArray['query'])) {
            parse_str($requestArray['query'], $args);
        }
        unset($requestArray);

        switch ($this->routeStyle) {
            case self::ROUTE_PATH:
                $this->routePath($request, $path, $args);
                break;
            case self::ROUTE_GET:
            default:
                $this->routeGet($request, $args);
                break;
        }
    }

    private function routePath($request, $path, $args) {
        // TODO
    }

    private function routeGet(MRequest $request, $args) {
        $route = array();
        if (array_key_exists($this->routeVar, $args)) {
            if ($args[$this->routeVar] == MApplication::ADMIN_MODULE && !empty($args[self::MODULE_ADMIN_ROUTE_VAR])) {
                // We are in a module admin part
                $request->isAdmin(true);
                $this->routeVar = self::MODULE_ADMIN_ROUTE_VAR;
                $this->deduceGetRoute($request);
                $this->routeVar = self::DEFAULT_ROUTE_VAR;
            } else {
                // It's a normal route method
                $this->deduceGetRoute($request);
            }
        } else if (isset(Mandrill::getApp()->defaultModule)) {
            $request->setModule(Mandrill::getApp()->defaultModule);
            $request->setController($this->defaultController);
            $request->setAction($this->defaultAction);
            $params = $this->_getParams($args);
            $request->setParams($params);
            unset($params);
        } else {
            throw new MException(MTranslator::translate('mandrill.web.router.routeNotSpecified'));
        }
    }

    public function deduceRoute(MRequest $request) {
        switch ($this->routeStyle) {
            case self::ROUTE_PATH:
                $this->deducePathRoute($request);
                break;
            case self::ROUTE_GET:
            default:
                $this->deduceGetRoute($request);
                break;
        }
    }

    public function deduceGetRoute(MRequest $request) {
        $requestArray = parse_url($request->getUrl());
        $path = (isset($requestArray['path'])) ? $requestArray['path'] : NULL;
        $args = array();
        if (isset($requestArray['query'])) {
            parse_str($requestArray['query'], $args);
        }
        unset($requestArray);
        $route = array();
        if (array_key_exists($this->routeVar, $args)) {
            $route = explode('/', $args[$this->routeVar]);
            if (count($route) >= 1) {
                $request->setModule($route[0]);
                if (isset($route[1]) && !empty($route[1])) {
                    $request->setController($route[1]);
                } else {
                    $request->setController($this->defaultController);
                }
                if (isset($route[2]) && !empty($route[2])) {
                    $request->setAction($route[2]);
                } else {
                    $request->setAction($this->defaultAction);
                }
                $params = $this->_getParams($args);
                $request->setParams($params);
                unset($params);
            } else {
                return NULL;
            }
            unset($route);
            unset($args);
        } else if (isset(Mandrill::getApp()->defaultModule)) {
            $request->setModule(Mandrill::getApp()->defaultModule);
            $request->setController($this->defaultController);
            $request->setAction($this->defaultAction);
            $params = $this->_getParams($args);
            $request->setParams($params);
            unset($params);
        } else 
            return NULL;
    }

    public function deducePathRoute(MRequest $request) {
        // TODO
    }

    public function getRoute(MRequest $request) {
        return $this->deduceRoute($request);
    }

    public static function createRoute($route, $params=array()) {
        $router = MRouter::getInstance();
        $routeArray = explode('/', $route);
        if ($router->routeStyle === self::ROUTE_PATH) {
            if (count($routeArray) < 3 || count($routeArray) > 4)
                throw new MException;
            else {
                return $route . $router->implodeParams($params, '/');
            }
        } else {
            return '?' . $router->routeVar . '=' . $route . $router->implodeParams($params);
        }
    }

    private function implodeParams($params = array(), $glue = '&') {
        if (!empty($params)) {
            $return = '';
            if ($glue == '&') {
                $equals = '=';
            } else {
                $equals = $glue;
            }
            foreach ($params as $key => $value) {
                $return .= $glue . $key . $equals . $value;
            }
            return $return;
        }
    }

    private function _getParams($args = NULL) {
        $params = array();
        $get = array();
        foreach ($args as $key => $value) {
            $get[$key] = $value;
        }
        $params['get'] = $get;
        $params['post'] = $_POST;

        return $params;
    }

}

?>
